﻿using StackExchange.Redis;
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;

namespace WeChat.PlatForm.Common.NoSqlHelp
{
    public class RedisHelp
    {

        /// <summary>
        /// 得到链接
        /// </summary>
        /// <returns></returns>
        private static ConnectionMultiplexer GetDataBase()
        {
            ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(AppConfig.GetRedisConn);

            return redis;
        }


        /// <summary>
        /// 写入地图列表
        /// </summary>
        /// <param name="key">地图上点的组key</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="dataId">该点的描述id（可存该点对应数据库中详细描述的id）</param>
        /// <returns></returns>
        public static bool GeoAdd(string key, double longitude, double latitude, string dataId)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                return DB.GeoAdd(key, new GeoEntry(longitude, latitude, dataId));
            }
        }

        /// <summary>
        /// 计算两点之间的距离
        /// </summary>
        /// <param name="key">在那个经纬度列表中查询</param>
        /// <param name="dataIdone">存入点中的数据唯一标示dataId</param>
        /// <param name="dateIdtwo"></param>
        /// <returns>如果返回null表示列表中无输入的点</returns>
        public static double? GeoDistance(string key, string dataIdone, string dateIdtwo)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                //计算两个点之间的距离，如果是null表示key的经纬度列表中不存在该id。Meters：精确到米
                return DB.GeoDistance(key, dataIdone, dateIdtwo, GeoUnit.Meters);
            }
        }

        /// <summary>
        /// 得到某个点周围的点的集合
        /// </summary>
        /// <param name="key">在那个经纬度列表中查询</param>
        /// <param name="dataId">点id</param>
        /// <param name="distance">距离</param>
        /// <returns>距离的键值对集合</returns>
        public static Dictionary<string, double?> GeoRadius(string key, string dataId, double distance)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                Dictionary<string, double?> dic = new Dictionary<string, double?>();

                IDatabase DB = redis.GetDatabase();

                GeoRadiusResult[] resul = DB.GeoRadius(key, dataId, distance, GeoUnit.Meters);

                foreach (GeoRadiusResult model in resul)
                {
                    dic.Add(model.Member, model.Distance);
                }

                return dic;
            }
        }

        /// <summary>
        /// 得到某个点周围的点的集合
        /// </summary>
        /// <param name="key">在那个经纬度列表中查询</param>
        /// <param name="longitude">经度</param>
        /// <param name="latitude">纬度</param>
        /// <param name="distance">距离</param>
        /// <returns>距离的键值对集合</returns>
        public static Dictionary<string, double?> GeoRadius(string key, double longitude, double latitude, double distance)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                Dictionary<string, double?> dic = new Dictionary<string, double?>();

                IDatabase DB = redis.GetDatabase();
               
                GeoRadiusResult[] resul = DB.GeoRadius(key, longitude, latitude, distance, GeoUnit.Meters);

                foreach (GeoRadiusResult model in resul)
                {
                    dic.Add(model.Member, model.Distance);
                }

                return dic;
            }
        }

        /// <summary>
        /// 插入数据库
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="time">过期时间</param>
        /// <returns></returns>
        public static bool SetRedis(string key, string value, TimeSpan? time = null)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                return DB.StringSet(key, value, time);
            }
        }

        /// <summary>
        /// 或得redis的值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string GetRedis(string key)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();

                string str = DB.StringGet(key);
                return str;
            }
        }

        /// <summary>
        /// 向左添加list
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string RedisPushLeft(string key, string values)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                long count = DB.ListLeftPush(key, values);

                return count.ToString();
            }
        }

        /// <summary>
        /// 从左侧拿取list
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string RedisGetLeft(string key)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                RedisValue str = DB.ListLeftPop(key);

                return str;
            }
        }

        /// <summary>
        /// 向右添加list
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string RedisPushRight(string key, string values)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                long count = DB.ListRightPush(key, values);

                return count.ToString();
            }
        }

        /// <summary>
        /// 从右边侧拿取list
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string RedisGetRight(string key)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                RedisValue str = DB.ListRightPop(key);

                return str;
            }
        }

        /// <summary>
        /// 拿出所有list中数据
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public static string[] RedisGetRange(string key)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                RedisValue[] str = DB.ListRange(key);

                return str.ToStringArray();
            }
        }

        /// <summary>
        /// redis给某个方法打分（会追加分）可用于记录页面访问次数
        /// </summary>
        /// <param name="key">某组的唯一标示</param>
        /// <param name="name">关键字名称</param>
        /// <param name="soce">增加的分数</param>
        /// <returns></returns>
        public static async Task<double> SortedSetIncrement(string key, string name, double soce)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                IDatabase DB = redis.GetDatabase();
                double str = await DB.SortedSetIncrementAsync(key, name, soce);
                return str;
            }
        }

        /// <summary>
        /// redis得到某个key中的打分集合
        /// </summary>
        /// <param name="key">某个打分的组的key</param>
        /// <param name="start">集合中的开始位置</param>
        /// <param name="end">结束位置</param>
        /// <param name="order">排序方式 0：降序 1：升序</param>
        /// <returns></returns>
        public static async Task<Dictionary<string, double>> SortedSetRangeByRankWithScores(string key,
            long start = 0, long end = -1, int order = 1)
        {
            using (ConnectionMultiplexer redis = GetDataBase())
            {
                Dictionary<string, double> dic = new Dictionary<string, double>();
                IDatabase DB = redis.GetDatabase();

                //默认升序
                Order orderModel = Order.Ascending;
                if (order == 0)
                {
                    orderModel = Order.Descending;
                }

                SortedSetEntry[] list = await DB.SortedSetRangeByRankWithScoresAsync(key, start, end, orderModel);

                foreach (SortedSetEntry model in list)
                {
                    dic.Add(model.Element, model.Score);
                }

                return dic;
            }
        }
    }
}
